package WSService

import (
	"encoding/json"
	"multimedia/utils"
	"sync"
	"time"

	log "github.com/sirupsen/logrus"
)

type Conference struct {
	usersList map[int64]*Session
	Id        int64
	Type      int
	Creator   int64
	EndTime   time.Time
	sync.RWMutex
}

func (r *Conference) InsertUser(s *Session, uid int64) int {
	r.Lock()
	defer r.Unlock()
	r.usersList[uid] = s
	log.WithField("func:", "InsertUser").Infof("the InsertUser the size is:%v the confierid is:%d", r.usersList, r.Id)
	return len(r.usersList)
}
func (r *Conference) GetUser(uid int64) *Session {
	r.RLock()
	defer r.RUnlock()
	user := r.usersList[uid]
	return user
}

func (r *Conference) NotifyAllRoomUser(p []byte, cmd int) {
	NotifyData := PacketResMsg(cmd, utils.Success, p)
	r.RLock()
	defer r.RUnlock()
	for _, v := range r.usersList {
		log.WithField("func:", "NotifyAllRoomUser").Infof("NotifyAllRoomUser the cmd is:%d the uid is:%d the list size is :%d",
			cmd, v.uid(), len(r.usersList))
		v.SendMessage(NotifyData, cmd)
	}
}
func (r *Conference) NotifyRoomUserExcludeUid(p []byte, cmd int, uid int64) {
	NotifyData := PacketResMsg(cmd, utils.Success, p)
	r.RLock()
	defer r.RUnlock()
	for oldUser, v := range r.usersList {
		if oldUser == uid {
			continue
		}
		v.SendMessage(NotifyData, cmd)
	}
}
func (r *Conference) UserEnterConfer(s *Session, uid int64) int {
	len := r.InsertUser(s, uid)
	ResData := PacketResMsg(utils.UserEnterRoomRes, utils.Success, nil)
	s.SendMessage(ResData, utils.UserEnterRoomRes)
	return len
}

func (r *Conference) UpdateUserName(s *Session, userName *WSUpdateUserNameReq) {
	notifyUserName := NotifyUserName{
		Uid:  userName.Uid,
		Name: userName.Name,
	}
	NotifyData, _ := json.Marshal(notifyUserName)
	r.NotifyAllRoomUser(NotifyData, utils.NotifyUserName)
	ResData := PacketResMsg(utils.UpdateUserNameRes, utils.Success, nil)
	log.WithField("func:", "UpdateUserName").Infof("updateusername res the uid is:%d", s.uid())
	s.SendMessage(ResData, utils.UpdateUserNameRes)
}
func (r *Conference) KickUser(s *Session, commPack *WSCommonReq) {
	comm := WSCommonReq{
		Uid: commPack.Uid,
	}
	kickUserData, _ := json.Marshal(comm)
	r.NotifyAllRoomUser(kickUserData, utils.NotifyKickUser)
	ResData := PacketResMsg(utils.KickUserRes, utils.Success, kickUserData)
	s.SendMessage(ResData, utils.KickUserRes)
	r.delUser(commPack.Uid)
}
func (r *Conference) CloseShared(s *Session, commPack *WSCommonReq) {
	comm := WSCommonReq{
		Uid: commPack.Uid,
	}
	NotifyData, _ := json.Marshal(comm)
	user := r.GetUser(commPack.Uid)
	if user != nil {
		NotifyData := PacketResMsg(utils.NotifyCloseShare, utils.Success, NotifyData)
		user.SendMessage(NotifyData, utils.NotifyCloseShare)
	}
	ResData := PacketResMsg(utils.CloseShareDesktopRes, utils.Success, NotifyData)
	s.SendMessage(ResData, utils.KickUserRes)
}
func (r *Conference) UpdateDeviceState(s *Session, userName *WSUpdateDeviceStateReq) {
	DeviceStateReq := WSUpdateDeviceStateReq{
		Uid:   userName.Uid,
		Id:    userName.Id,
		State: userName.State,
	}
	NotifyData, _ := json.Marshal(DeviceStateReq)
	if userName.Uid == 0 {
		r.NotifyAllRoomUser(NotifyData, utils.NotifyDeviceState)
	} else {
		user := r.GetUser(userName.Uid)
		if user != nil {
			NotifyData := PacketResMsg(utils.NotifyDeviceState, utils.Success, NotifyData)
			user.SendMessage(NotifyData, utils.NotifyDeviceState)
		}
	}
	ResData := PacketResMsg(utils.UpdateDeviceStateRes, utils.Success, nil)
	s.SendMessage(ResData, utils.UpdateDeviceStateRes)
}
func (r *Conference) StartWhiteBoard(s *Session, req string) {
	r.Lock()
	defer r.Unlock()
	NotifyData := PacketResMsg(utils.NotifyWhiteBoard, utils.Success, []byte(req))
	for oldUser, v := range r.usersList {
		if oldUser == s.uid() {
			continue
		}
		v.SendMessage(NotifyData, utils.NotifyWhiteBoard)
	}
}

func (r *Conference) CloseWhiteBoard(s *Session, req string) {
	NotifyData := PacketResMsg(utils.NotifyWhiteBoardEnd, utils.Success, []byte(req))
	r.RLock()
	defer r.RUnlock()
	for oldUser, v := range r.usersList {
		if oldUser == s.uid() {
			continue
		}
		v.SendMessage(NotifyData, utils.NotifyWhiteBoardEnd)
	}
}
func (r *Conference) TransferModerator(s *Session, req string) {
	r.NotifyRoomUserExcludeUid([]byte(req), utils.TransferModeratorReq, s.uid())
}
func (r *Conference) SendTextMessage(s *Session, req string) {
	r.NotifyAllRoomUser([]byte(req), utils.NotifyTextMessage)
}
func (r *Conference) SendUserTextMessage(s *Session, req string) {
	comm := &WSCommonReq{}
	err := json.Unmarshal([]byte(req), &comm)
	if err != nil {
		log.WithField("func:", "SendUserTextMessage").Infof("unmarshal the msg error :%v", err)
	}
	user := r.GetUser(comm.Uid)
	if user != nil {
		log.WithField("func:", "SendUserTextMessage").Infof("the user is exist %d", comm.Uid)
		NotifyData := PacketResMsg(utils.NotifyUserTextMessage, utils.Success, []byte(req))
		user.SendMessage(NotifyData, utils.NotifyUserTextMessage)
	} else {
		log.WithField("func:", "SendUserTextMessage").Infof("the user is not exist %d", comm.Uid)
	}
}
func (r *Conference) ForwardMsg(s *Session, req string) {
	comm := WSCommonReq{}
	err := json.Unmarshal([]byte(req), &comm)
	if err != nil {
		log.WithField("func:", "ForwardMsg ").Infof("unmarshal the msg error :%v", err)
	}
	user := r.GetUser(comm.Uid)
	if user != nil {
		NotifyData := PacketResMsg(utils.AckStartRecordRes, utils.Success, []byte(req))
		user.SendMessage(NotifyData, utils.AckStartRecordRes)
	}
}
func (r *Conference) AckStartRecord(s *Session, req string) {
	comm := &WSCommonReq{}
	err := json.Unmarshal([]byte(req), &comm)
	if err != nil {
		log.WithField("func:", "AckStartRecord").Infof("unmarshal the msg error :%v", err)
	}
	log.WithField("func:", "AckStartRecord").Infof("the comm uid is:%d the creator is:%d", comm.Uid, r.Creator)
	user := r.GetUser(comm.Uid)
	if user != nil {
		log.WithField("func:", "AckStartRecord").Infof("the user is exist %d", comm.Uid)
		NotifyData := PacketResMsg(utils.AckStartRecordReq, utils.Success, []byte(req))
		user.SendMessage(NotifyData, utils.AckStartRecordReq)
	} else {
		NotifyData := PacketResMsg(utils.AckStartRecordRes, utils.TheHostNotExist, nil)
		s.SendMessage(NotifyData, utils.AckStartRecordRes)
		log.WithField("func:", "AckStartRecord").Infof("the user is not exist %d", comm.Uid)
		return
	}
}
func (r *Conference) delUser(uid int64) (int, int, int64) {
	r.Lock()
	defer r.Unlock()
	if uid == -1 {
		return len(r.usersList), r.Type, r.Creator
	}
	_, ok := r.usersList[uid]
	if ok {
		delete(r.usersList, uid)
	}
	return len(r.usersList), r.Type, r.Creator
}
func (r *Conference) NotifyUserStartRecord(s *Session, p string) {
	r.NotifyRoomUserExcludeUid([]byte(p), utils.NotifyStartRecord, s.uid())
	ResData := PacketResMsg(utils.StartRecordRes, utils.Success, nil)
	s.SendMessage(ResData, utils.StartRecordRes)
	log.WithField("func:", "NotifyUserStartRecord").Infof(" msg is:%s", p)
}
